﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Entities.Portals;
using DotNetNuke.Entities.Tabs;
using DotNetNuke.Modules.PowerShell.Args;
using DotNetNuke.Services.Exceptions;
using DotNetNuke.Services.Localization;
using DotNetNuke.Web.UI;
using System.Text;

namespace DotNetNuke.Modules.PowerShell.Contexts
{
	public class PageContext : BaseContext
	{

		public override void Process(IContextArgs args)
		{
			base.Process(args);

			if (IsValid)
			{
				var arg = args.Arguments;

				string relativeTab = arg.ContainsKey("r") ? arg["r"] : string.Empty;
				string location = arg.ContainsKey("l") ? arg["l"] : "a";
				string tabPath = arg.ContainsKey("n") ? arg["n"] : string.Empty;
				bool includedInMenu = arg.ContainsKey("m") ? arg["m"] == "1" : true;
				string template = arg.ContainsKey("t") ? arg["t"] : string.Empty;

				switch (args.Action)
				{
					case "add":
						if (string.IsNullOrEmpty(tabPath))
						{
							AddResult("Please input the new page name.");
						}
						else if (string.IsNullOrEmpty(relativeTab))
						{
							AddResult("Please input the relative page name.");
						}
						else
						{
							TabRelativeLocation relativeLocation = GetRelativeLocation(location);
							foreach (var tabGroup in tabPath.Split(';'))
							{
								var tabLevels = tabGroup.Split('/');
								AddPage(tabLevels[0], relativeTab, relativeLocation, template, includedInMenu);
								if(tabLevels.Length > 1)
								{
									var parentTab = tabLevels[0];
									for (int i = 1; i < tabLevels.Length; i++)
									{
										foreach (var path in tabLevels[i].Split(','))
										{
											AddPage(path, parentTab, TabRelativeLocation.CHILD, template, includedInMenu);
										}
										parentTab = tabLevels[i].Split(',')[0];
									}
								}

								if(relativeLocation != TabRelativeLocation.CHILD)
								{
									relativeTab = tabLevels[0];
								}
							}
						}

						break;
					case "list":
						GetPageList();
						break;
					case "del":
						DeletePage(tabPath);
						break;
					default:
						AddResult("No Action");
						break;
				}
			}
		}

		private void DeletePage(string tabPath)
		{
			var tabCtrl = new TabController();
			var tabInfo = tabCtrl.GetTabByName(tabPath, PortalSettings.Current.ActiveTab.PortalID);
			if (tabInfo != null)
			{
				tabCtrl.DeleteTab(tabInfo.TabID, tabInfo.PortalID);
				AddResult(string.Format("Delete '{0}' successful!", tabPath));
			}
			else
			{
				AddResult(string.Format("'{0}' doesn't exsit", tabPath));
			}
		}

		private void GetPageList()
		{
			var tabList = new TabController().GetTabsByPortal(PortalSettings.Current.ActiveTab.PortalID);
			foreach (var tab in tabList.Values)
			{
				AddResult(tab.FullUrl);
			}
		}

		private TabRelativeLocation GetRelativeLocation(string location)
		{
			switch (location)
			{
				case "a":
					return TabRelativeLocation.AFTER;
				case "b":
					return TabRelativeLocation.BEFORE;
				case "c":
					return TabRelativeLocation.CHILD;
				default:
					return TabRelativeLocation.AFTER;
			}
		}

		private void AddPage(string tabPath, string relativeTab, TabRelativeLocation location, string template, bool includedInMenu)
		{
			var tabCtrl = new TabController();

			TabInfo selectedTab = tabCtrl.GetTabByName(relativeTab, PortalSettings.Current.ActiveTab.PortalID);
			TabInfo newTab = RibbonBarManager.InitTabInfoObject(selectedTab, location);

			string templateFile = string.Empty;
			if ((!string.IsNullOrEmpty(template)))
			{
				templateFile = Path.Combine(PortalSettings.Current.HomeDirectoryMapPath, "Templates\\" + template);
			}

			newTab.TabName = tabPath;
			newTab.IsVisible = includedInMenu;

			string errMsg = string.Empty;
			try
			{
				RibbonBarManager.SaveTabInfoObject(newTab, selectedTab, location, templateFile);
			}
			catch (Exception ex)
			{
				Exceptions.LogException(ex);
				errMsg = ex.Message;
			}

			//Clear the Tab's Cached modules
			DataCache.ClearModuleCache(PortalSettings.Current.ActiveTab.TabID);

			//Update Cached Tabs as TabPath may be needed before cache is cleared
			TabInfo tempTab;
			if (new TabController().GetTabsByPortal(PortalSettings.Current.ActiveTab.PortalID).TryGetValue(newTab.TabID, out tempTab))
			{
				tempTab.TabPath = newTab.TabPath;
			}

			if ((string.IsNullOrEmpty(errMsg)))
			{
				AddResult(string.Format("Page '{0}' add successful.", tabPath));
			}
			else
			{
				AddResult(string.Format("<p>{0}</p>", errMsg));
			}
		}

		public override string Help
		{
			get
			{
				StringBuilder help = new StringBuilder();
				help.Append(
@"Page Context is used to manage pages in your portal.
It Can Add, List, Delete pages
	page add
		Parameters: 
			n: Page name; 
			r: Relative Page Name; 
			l: Relative location, b->before/a->after/c->child of, default is after;
			t: template name, default is default template;
			m: whether include in menu 0->not include 1->include, default is 1
		e.g: page add n:Test r:Home l:a
		this command will add a page named 'Test' after 'Home'.
");

				return help.ToString();
			}
		}
	}
}